package cinvestav.adviseme.webservice;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;

import cinvestav.adviseme.controller.PersonaController;
import cinvestav.adviseme.databasemodel.PersonaDB;
import cinvestav.adviseme.datamodel.Persona;
import cinvestav.adviseme.util.DBException;
import cinvestav.adviseme.util.DataBaseDictionary;
import cinvestav.adviseme.util.QueryParamDictionary;

@Path("/persona")
public class PersonaWebService {

	protected PersonaController personaController;
	protected PersonaDB personaDB;
	
	public PersonaWebService() throws DBException {
		// TODO Auto-generated constructor stub
		personaController = new PersonaController();
		personaDB = new PersonaDB();
	}
	
	
	@GET
	@Produces({MediaType.APPLICATION_JSON })
	@Path("/getAll")
	/**
	 * Obtiene todas las personas almacenadas en la base de datos
	 */
	public List<Persona> getAllPersona() {
		try {
			List<Persona> res = personaController.getAll();
			if (res.isEmpty()) res.add(new Persona());
			return res;
		} catch (DBException e) {
			// TODO Auto-generated catch block
			Logger.getLogger(PersonaWebService.class.getName()).log(Level.SEVERE,null,e);
			throw new WSErrorException(e.getMessage());
		}
	}
	
	@POST
	@Produces({MediaType.APPLICATION_JSON})
	@Consumes({MediaType.APPLICATION_JSON})
	@Path("/getByFilters")
	public List<Persona> getPersonaByFilters(JSONObject requestPersonaJSON){
		//Los parametros se obtienen como un objeto JSON y es necesario realizar el
		//parseo
		try {
			//Objeto que almacenara la persona en formato JSON
			JSONObject personaJSON;
			//Lista de resultados
			List<Persona> res = new LinkedList<Persona>();
			//Persona que almacenara los filtros ingresados por parametro
			Persona personaFilter = new Persona();
			//Variables que indicaran el tipo de busqueda que se utilizara
			Boolean busquedaAmigos;
			Boolean busquedaPersonaByID;
			Boolean busquedaPersonaGeneral;
			Boolean login;
			try {
				Logger.getLogger(PersonaWebService.class.getName()).log(
						Level.INFO,
						"request = " + requestPersonaJSON.toString());
				//Se obtiene el objeto JSON del REQUEST, mediante el nombre
				//de parametro ingresado
				personaJSON = new JSONObject(
						requestPersonaJSON
								.getString(QueryParamDictionary.PERSONA_PARAM));

				/**
				 * Se obtienen cada uno de los campos necesarios en este caso se utilizaran unicamente
				 * 	Correo
				 * 	ID
				 * 	Nombre de Usuario
				 * 	Password
				 * 	Nombre de la Persona
				 * 	Apellido Paterno
				 * 	Apellido Materno
				 */
				personaFilter.setCorreo(personaJSON.getString("correo"));
				personaFilter.setId(personaJSON.getInt("id"));
				personaFilter.setNombreUsuario(personaJSON
						.getString("nombreUsuario"));
				personaFilter.setPassword(personaJSON.getString("password"));
				personaFilter.setNombrePersona(personaJSON.getString("nombrePersona"));
				personaFilter.setApellidoMaterno(personaJSON.getString("apellidoMaterno"));
				personaFilter.setApellidoPaterno(personaJSON.getString("apellidoPaterno"));

				Logger.getLogger(PersonaWebService.class.getName()).log(
						Level.INFO,
						"String = |" + personaFilter.getNombreUsuario() + " | "
								+ personaFilter.getId() + " | "
								+ personaFilter.getPassword() + " | "
								+ personaFilter.getCorreo() + " | "+personaFilter.getNombreCompleto()+ " |") ;
			} catch (JSONException e) {
				// Si ocurre un error al parsear los parametros se retorna este error al cliente
				Logger.getLogger(PersonaWebService.class.getName()).log(Level.SEVERE,null,e);
				throw new WSErrorException("PARAMETROS INCORRECTOS");
			}
			
			//Validacion del tipo de busqueda que se desea realizar
			busquedaAmigos = personaFilter.getId() != 0
					& (!personaFilter.getNombreUsuario().isEmpty()
							| !personaFilter.getCorreo().isEmpty() | !personaFilter
							.getNombreCompleto().equals("  "))
					& personaFilter.getPassword().isEmpty();

			busquedaPersonaGeneral = personaFilter.getId() == 0
					& (!personaFilter.getNombreUsuario().isEmpty()
							| !personaFilter.getCorreo().isEmpty() | !personaFilter
							.getNombreCompleto().equals("  "))
					& personaFilter.getPassword().isEmpty();

			busquedaPersonaByID = personaFilter.getId() != 0
					& (personaFilter.getNombreUsuario().isEmpty()
							& personaFilter.getCorreo().isEmpty() & personaFilter
							.getNombreCompleto().equals("  "))
					& personaFilter.getPassword().isEmpty();

			login = personaFilter.getId() == 0
					& (!personaFilter.getNombreUsuario().isEmpty() & !personaFilter
							.getPassword().isEmpty());

			Logger.getLogger(PersonaWebService.class.getName()).log(
					Level.INFO,
					"BG = " + busquedaPersonaGeneral + " BP= "
							+ busquedaPersonaByID + " BA=" + busquedaAmigos
							+ " L=" + login);

			/*
	         * Mapa para los filtros seleccionados
	         *      Key = Filtro a utilizar, definido en la clase "DataBaseDictionary"
	         *      Value = Sera un arreglo de dos posiciones donde:
	                    [0] = Valor a buscar en la base (Valor del campo)
	         *          [1] = Tipo de Dato, deacuerdo a este se realizara el set en el
	         *                  PreparedStatement, Los tipos validos estan definidos en "DataBaseDictionary"
	         */
			Map<String, String[]> mapaConsulta = new HashMap<String, String[]>();
			String[] valor = new String[2];

			if (busquedaPersonaByID) {
				// Se agrega una entrada al mapa
				valor = new String[2];
				valor[0] = personaFilter.getId().toString();
				valor[1] = DataBaseDictionary.COLUMN_TYPE_PERSONA_ID;
				mapaConsulta
						.put(DataBaseDictionary.COLUMN_FILTER_NAME_PERSONA_ID,
								valor);
				res = personaController.getByFilters(mapaConsulta);

			} else if (login) {
				// Se agrega al nombre de usuario al mapa
				valor = new String[2];
				valor[0] = personaFilter.getNombreUsuario();
				valor[1] = DataBaseDictionary.COLUMN_TYPE_PERSONA_NOMBREUSUARIO;
				mapaConsulta
						.put(DataBaseDictionary.COLUMN_FILTER_NAME_PERSONA_NOMBREUSUARIO,
								valor);

				// Agregar el password al mapa
				valor = new String[2];
				valor[0] = personaFilter.getPassword();
				valor[1] = DataBaseDictionary.COLUMN_TYPE_PERSONA_PASSWORD;
				mapaConsulta.put(
						DataBaseDictionary.COLUMN_FILTER_NAME_PERSONA_PASSWORD,
						valor);
				res = personaController.getByFilters(mapaConsulta);

			} else {

				if (!personaFilter.getNombreUsuario().isEmpty()) {
					// Se agrega al nombre de usuario al mapa
					valor = new String[2];
					valor[0] = personaFilter.getNombreUsuario();
					valor[1] = DataBaseDictionary.COLUMN_TYPE_PERSONA_NOMBREUSUARIO_LIKE;
					mapaConsulta
							.put(DataBaseDictionary.COLUMN_FILTER_NAME_PERSONA_NOMBREUSUARIO_LIKE,
									valor);
				}

				if (!personaFilter.getCorreo().isEmpty()) {
					// Se agrega el correo al mapa
					valor = new String[2];
					valor[0] = personaFilter.getCorreo();
					valor[1] = DataBaseDictionary.COLUMN_TYPE_PERSONA_CORREO;
					mapaConsulta
							.put(DataBaseDictionary.COLUMN_FILTER_NAME_PERSONA_CORREO,
									valor);
				}
				if (!personaFilter.getNombrePersona().isEmpty()) {
					// Se agrega el nombre de la persona al mapa
					valor = new String[2];
					valor[0] = personaFilter.getNombrePersona();
					valor[1] = DataBaseDictionary.COLUMN_TYPE_PERSONA_NOMBREPERSONA;
					mapaConsulta
							.put(DataBaseDictionary.COLUMN_FILTER_NAME_PERSONA_NOMBREPERSONA,
									valor);
				}
				if (!personaFilter.getApellidoPaterno().isEmpty()) {
					// Se agrega el apellido paterno al mapa
					valor = new String[2];
					valor[0] = personaFilter.getApellidoPaterno();
					valor[1] = DataBaseDictionary.COLUMN_TYPE_PERSONA_APELLIDO_PATERNO;
					mapaConsulta
							.put(DataBaseDictionary.COLUMN_FILTER_NAME_PERSONA_APELLIDO_PATERNO,
									valor);
				}
				if (!personaFilter.getApellidoMaterno().isEmpty()) {
					// Se agrega el apellido materno al mapa
					valor = new String[2];
					valor[0] = personaFilter.getApellidoMaterno();
					valor[1] = DataBaseDictionary.COLUMN_TYPE_PERSONA_APELLIDO_MATERNO;
					mapaConsulta
							.put(DataBaseDictionary.COLUMN_FILTER_NAME_PERSONA_APELLIDO_MATERNO,
									valor);
				}

				if (busquedaAmigos) {
					
					res = personaController.getFriendsByFilters(personaFilter,
							mapaConsulta);
				} else if (busquedaPersonaGeneral) {
					res = personaController.getByFilters(mapaConsulta);
				} else {
					throw new WSErrorException("ERROR CONSULTA INCORRECTA");
				}

			}

			if (res.isEmpty()) {
				res.add(new Persona());
			}

			return res;
		} catch (DBException e) {
			Logger.getLogger(PersonaWebService.class.getName()).log(
					Level.SEVERE, null, e);
			throw new WSErrorException(e.getMessage());
		}
	}
	
	@GET
	@Produces({MediaType.APPLICATION_JSON })
	@Path("/getAllFriends")
	public List<Persona> getAllFriends(@QueryParam(QueryParamDictionary.PERSONA_ID_PARAM) String id_Per){
		try {
			Logger.getLogger(PersonaWebService.class.getName()).log(Level.INFO,"GET FRIEND ID="+id_Per);
			Persona personafiltro = new Persona();
			personafiltro.setId(Integer.parseInt(id_Per));
			List<Persona> res = personaController.getFriends(personafiltro);
			if (res.isEmpty()) res.add(new Persona());
			Logger.getLogger(PersonaWebService.class.getName()).log(Level.INFO,"GET FRIEND RES="+res);
			return res;
		} catch (DBException e) {
			// TODO Auto-generated catch block
			Logger.getLogger(PersonaWebService.class.getName()).log(Level.SEVERE,null,e);
			throw new WSErrorException(e.getMessage());
		}
		
	}
	
	@GET
	@Produces({MediaType.APPLICATION_JSON })
	@Path("/deleteFriendShip")
	public Persona deleteFriendShip(@QueryParam(QueryParamDictionary.PERSONA_ID_ORIGEN) String perori,@QueryParam(QueryParamDictionary.PERSONA_ID_DESTINO) String perdes){
		Map<String,String[]> queryMap = new HashMap<String,String[]>();
		String values[] = new String[2];
		List<Persona> personas1 = new LinkedList<Persona>();
		List<Persona> personas2 = new LinkedList<Persona>();
		
		values[0] = perori;
		values[1] = DataBaseDictionary.COLUMN_TYPE_PERSONA_ID;
		
		queryMap.put(DataBaseDictionary.COLUMN_FILTER_NAME_PERSONA_ID, values);
		try{
			personas1 = personaDB.getByFiter(queryMap);
			Persona persona1 = personas1.get(0);
			
			values[0] = perdes;
			queryMap.put(DataBaseDictionary.COLUMN_FILTER_NAME_PERSONA_ID, values);
			personas2 = personaDB.getFriendsByFilter(persona1, queryMap);
			if (!personas2.isEmpty()){				
				Persona persona2 = personas2.get(0);
				personaController.deleteFriendShip(persona1, persona2);
				return new Persona();
			}else{
				throw new WSErrorException("No se encontro a la persona");
			}			
		}catch(DBException e){
			// TODO Auto-generated catch block
			Logger.getLogger(PersonaWebService.class.getName()).log(Level.SEVERE,null,e);
			throw new WSErrorException(e.getMessage());
		}
		
		//personaController.deleteFriendShip(personaOrigen, personaDestino);				
	}
}
